﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using TimeTrak.DAL;
using System.Timers;
using System.ComponentModel;

namespace TimeTrak.BLL
{

    /// <summary>
    /// The top level, core controlling class
    /// </summary>
    public class TimeTrakController
    {
        TimeManager tm;
        public BindingTaskList TaskList { get; set; }
        DataAccess da;
        int maxID;

        public string CurrentDataPath { get; private set; }
        private const TimeUnitType DEFAULT_TIME_UNIT = TimeUnitType.Hour;


        public TimeTrakController(MainForm viewForm)
        {
            try
            {

                tm = new TimeManager();
                tm.TimerTick += new TickEventHandler(tm_TimerTick);

                da = new DataAccess();

            }
            catch (Exception ex)
            {
                throw new Exception("Error initializing TimeTrakController!", ex);
            }

        }

        void AddNewTaskToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        void NewToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        void OpenToolStripMenuItem_Click(object sender, EventArgs e)
        {
            throw new NotImplementedException();
        }

        void tm_TimerTick(object sender, System.Timers.ElapsedEventArgs e)
        {
            SaveData();
        }

        public void SaveData()
        {
            try
            {
                if (CurrentDataPath != null)
                {
                    UpdateTaskTimes();
                    da.SaveTaskList(TaskList.ToList<Task>(), CurrentDataPath);
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error persisting data!", ex);
            }
        }

        internal void SetTracking(int taskID, bool value)
        {
            if (value == true)
            {
                //stop time on all other tasks
                foreach (Task item in TaskList)
                {
                    if (item.ID != taskID && item.IsRunning)
                    {
                        item.StopTime();
                    }
                    else if (item.ID == taskID)
                    {
                        item.StartTime();
                    }
                }


            }
            else
            {
                foreach (Task item in TaskList)
                {
                    if (item.ID == taskID)
                    {
                        item.StopTime();
                        break;
                    }
                }
                this.SaveData();
            }


        }

        public void UpdateTaskTimes()
        {
            try
            {
                if (TaskList != null)
                {
                    foreach (Task item in TaskList)
                    {
                        if (item.IsRunning)
                        {
                            item.UpdateTime();
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Error updating task times!", ex);
            }
        }

        public TimeSpan GetHoursForDate(DateTime date)
        {
            TimeSpan total = new TimeSpan();
            foreach (Task item in TaskList)
            {
                foreach (TimeRecord rec in item.TimeRecordList)
                {
                    //record was entierly in this date
                    if (rec.StartTime.Date == date && rec.EndTime.Date == date)
                    {
                        total = total.Add(rec.GetDuration());
                    }
                    //record started before the date but ended during the date
                    else if (rec.StartTime.Date < date && rec.EndTime.Date == date)
                    {
                        //get the part that was during the date
                        TimeSpan temp = rec.EndTime.Subtract(date);
                        total = total.Add(temp);
                    }
                    //record started during the date, but ended after the date
                    else if (rec.StartTime.Date == date && rec.EndTime.Date > date)
                    {
                        //get the part that was during the date
                        TimeSpan temp = date.AddDays(1).Subtract(rec.StartTime);
                        total = total.Add(temp);
                    }
                }
            }

            return total;

        }

        public TimeSpan GetHoursWTD(DateTime date)
        {
            int days = date.DayOfWeek - DayOfWeek.Monday;
            DateTime start = date.AddDays(-days);
            DateTime current = start;

            TimeSpan total = new TimeSpan();
            while (current <= date)
            {
                total = total.Add(this.GetHoursForDate(current));
                current = current.AddDays(1);
            }


            return total;
        }

        internal void AddNewTask()
        {
            maxID++;
            TaskList.Add(new Task(maxID, "", false, false, 0m, DEFAULT_TIME_UNIT, new List<TimeRecord>(), "", 5));

        }

        internal void DeleteTask(int id)
        {
            foreach (Task item in TaskList)
            {
                if (item.ID == id)
                {
                    TaskList.Remove(item);
                    SaveData();
                    break;
                }
            }
        }

        public Task GetTask(int id)
        {
            Task myTask = null;
            foreach (Task item in TaskList)
            {
                if (item.ID == id)
                {
                    myTask = item;
                    break;
                }
            }
            return myTask;
        }

        internal void LoadDataFile(string filePath)
        {
            try
            {
                TaskList = new BindingTaskList(da.GetTaskList(filePath));

                //if the application was shutdown before stopping time tacking
                //reset the tasks to a stopped state
                //also, get the max ID of the current list

                maxID = -1;
                foreach (Task item in TaskList)
                {
                    item.IsRunning = false;
                    item.CurrentTimeRecord = null;
                    if (item.ID > maxID)
                    {
                        maxID = item.ID;
                    }
                }

                CurrentDataPath = filePath;

                tm.Start();

            }
            catch (Exception ex)
            {
                throw new Exception("Error loading data file!", ex);
            }

        }

        internal void CreateNewDataFile(string filePath)
        {
            try
            {
                da.SaveTaskList(new List<Task>(), filePath);
                LoadDataFile(filePath);
            }
            catch (Exception ex)
            {
                throw new Exception("Error creating new data file!", ex);
            }
        }

        internal void ShowView()
        {
            LoadView();
            Application.Run(new MainForm());

        }

        private void LoadView()
        {
           //get data from model

            //do any processing needed for view preparation


            //set values of controls in view


        }
    }
}
